package com.bitmain.mmst.miner.monitor.executor;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;

import org.apache.commons.lang3.StringUtils;

import com.bitmain.mmst.miner.monitor.internal.MonitorOption;

/**
 * 
 *
 * @author Richard - rui.wu@bitmain.com
 * @since 2016年7月6日
 *
 */
public class MinerCommandExecutor extends AbstractMinerExecutor<MinerCommandExecutor, MinerCommandMessage>{
	private MinerCommandMessage message;
	private int command;

	public MinerCommandExecutor(MinerCommandMessage message,int command){
		super(MinerCommandExecutor.class);
		this.message = message;
		this.command = command;
	}

	@Override
	public MinerCommandMessage execute() {
		System.out.println("【实时检测】"+message.getHost()+"执行了实时检测");
		String host = message.getHost();
		int port = message.getPort();
		if((Command.ALL.key&command)!=0||(Command.STATS.key&command)!=0){
			String stats = request(host,port,Command.STATS.value);
			message.setStats(stats);
			System.out.println("stats————"+stats);
			if(StringUtils.isNotEmpty(stats)){
				message.setStatsable(true);
			}else{
				message.setStatsable(false);
			}
				
		}
		if((Command.ALL.key&command)!=0||(Command.POOLS.key&command)!=0){
			String pools = request(host,port,Command.POOLS.value);
			message.setPools(pools);
			System.out.println("pools————"+pools);
			if(StringUtils.isNoneEmpty(pools)){
				message.setPoolsable(true);
			}else{
				message.setPoolsable(false);
			}
		}
		if((Command.ALL.key&command)!=0||(Command.SUMMARY.key&command)!=0){
			String summary = request(host,port,Command.SUMMARY.value);
			message.setSummary(summary);
			System.out.println("summary————"+summary);
			if(StringUtils.isNotEmpty(summary)){
				message.setSummaryable(true);
			}else{
				message.setSummaryable(false);
			}
		}
		return message;
	}

	private String request(String host, int port, String cmd) {
		Socket socket = null;
		BufferedWriter writer = null;
		BufferedReader reader = null;
		StringBuilder response = new StringBuilder();

		try {
			socket = new Socket();
			socket.setSoTimeout(MonitorOption.socketOvertime);
			socket.connect(new InetSocketAddress(host,port));

			writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			writer.write(cmd);
			writer.flush();

			reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

			String line;
			while((line=reader.readLine())!=null){
				response.append(line);
			}
		} catch (Exception e) {
			System.out.println("从矿机中读取数据发生错误");
			return null;
		} finally{
			try {
				if(socket!=null){
					socket.close();
				}
				if(writer!=null){
					writer.close();
				}
				if(reader!=null){
					reader.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return response.toString().trim();
	}
	
	/**
	 * 矿机命令行枚举
	 *
	 * @author Kweny - enkun.jiang@bitmain.com
	 * @since 2015年11月24日
	 *
	 */
	public static enum Command {
		/**
		 * 矿机MAC地址命令
		 */
		MAC("", 1 << 1),
		/**
		 * 矿机状态信息命令
		 */
		STATS("{\"command\":\"stats\"}", 1 << 2),
		/**
		 * 矿机汇总信息命令
		 */
		SUMMARY("{\"command\":\"summary\"}", 1 << 3),
		/**
		 * 矿机矿池配置信息命令
		 */
		POOLS("{\"command\":\"pools\"}", 1 << 4),
		/**
		 * 所有命令
		 */
		ALL("", 1 << 5);
		
		public int key;
		public String value;
		
		private Command(String value, int key) {
			this.value = value;
			this.key = key;
		}
	}
}
